Intent可以做到將現在的Activity跳到另外一個Activity的效果,比方說我可以製作一個登入介面,登入後就會跳到App的主畫面;又或者按下一個按鈕就跳到搜尋天氣資訊的介面......。
首先附上這次的GitHub
本次實作會製作三個介面:
登入介面是App開啟時最先看到的介面,接著因為沒有註冊就不能登入所以也設計了一個註冊的介面,會用Dialo來顯示,註冊完就可以用帳號密碼登入,最後就會用Intent跳轉到MainActivity。
可以從專案名稱按右鍵 > New > Activity > Empty Views Activity
這樣可以建立一個乾淨的Activity並且同時建立一個布局檔,可以省一點步驟
接著為你的Activity命名,他會同時幫你把layout也命名,最後按下finish就成功建立囉~
由於這次的設定跟程式碼都偏長,布局的部分我就都以圖文解說為主,程式的部分再將重點部分貼上來解說。
首先登入介面,這次我設計了一個可以輸入帳密的兩個EditText;放了兩張跟帳號密碼有關的圖在旁邊,這部分我使用TextView放置圖片,用到了background將複製進drawable的圖片給引入;接著放了一個煞有其事的圖片在上面,這部分我使用到了ImageView
這個物件,使用方法很簡單,一放出來之後就會跳出這個畫面
將想放入的圖片事先加進Drawable,就可以在畫面左下那個清單內找到,選取後在按下右下方的Ok
就成功將圖片放進介面內囉~除此之外也可以使用android studio內建的圖片;接著放了註冊按鈕以及登入按鈕,本次的設計中會用一種很偷懶的方式存取帳號跟密碼,這部分就到了程式的部分再細說。
這裡我添加了兩個EditText來輸入要註冊的帳號密碼,按下建立後會將輸入的帳號跟密碼存入陣列中,並且關閉Dialog,按下取消就是直接關閉Dialog。
這次的主角不是主畫面,所以這裡我就做得比較隨便了,隨便弄一個TextView讓人看得出有換Activity而已。
這次的實作除了會寫Login的Activity以外,還會新建一個class,用來創立一個ArrayList來簡單的做到動態新增帳號密碼的功能,要注意的是,本次實作使用的方式,每次開啟App時都會將陣列給清空,因此如果只是當下會用到的話倒是是可以考慮這種存取方式,但如果是想存取像帳號密碼這種需要一直存在的資料的話,最好還是結合內建的資料庫系統來存取會比較好,例如:SharedPreferences、Room、SQLite。
首先建立一個class命名為AccountPasswordData
import java.util.ArrayList;
import java.util.HashMap;
public class AccountPasswordData {
private ArrayList<HashMap<String,String>> data = new ArrayList<>();
public void setActPwdData(String account,String password){
HashMap hashMap = new HashMap();
hashMap.put("Account",account);
hashMap.put("Password",password);
this.data.add(hashMap);
}
public ArrayList<HashMap<String,String>> getActPwdData(){
return data;
}
}
可以看到我在第一行先創立了一個ArrayList,並且規定裡面的資料要以HashMap的形式存取
public void setActPwdData(String account,String password){
HashMap hashMap = new HashMap();
hashMap.put("Account",account);
hashMap.put("Password",password);
this.data.add(hashMap);
}
接著撰寫了一個方法setActPwdData
用來存取帳號跟密碼,呼叫這個方法時還要傳入帳號跟密碼,接著可以看到我建立了一個hashMap,然後就將接收到的帳號跟密碼傳入,最後再把輸入完資料的hashMap丟給我的ArrayList
public ArrayList<HashMap<String,String>> getActPwdData(){
return data;
}
最後看到getActPwdData
這裡,我將個方法設計成呼叫後會傳回data。
private EditText account,password;
private Button register,login;
private Dialog dialog;
private AccountPasswordData accountPasswordData;
將該宣告的物件都宣告,因為會使用到Dialog以及AccountPasswordData,所以這裡也要進行宣告
account = findViewById(R.id.account);
password = findViewById(R.id.password);
register = findViewById(R.id.register_button);
login = findViewById(R.id.login_button);
dialog = new Dialog(this);
dialog.setContentView(R.layout.register_dialog);
accountPasswordData = new AccountPasswordData();
register.setOnClickListener(view -> setDialog());
login.setOnClickListener(view -> checkActPwdData(account.getText().toString(),password.getText().toString()));
Dialog的部分一樣先初始化並綁定頁面,accountPasswordData也是進行初始化的動作,接著就是兩個按鈕的點擊事件,註冊按鈕按下後會呼叫設定Dialog的方法,登入按鈕則是呼叫檢查帳密的方法並把輸入的帳密也傳進去。
private void setDialog() {
dialog.show();
EditText register_act = dialog.findViewById(R.id.register_act);
EditText register_pwd = dialog.findViewById(R.id.register_pwd);
Button cancel = dialog.findViewById(R.id.cancel);
Button create = dialog.findViewById(R.id.create);
cancel.setOnClickListener(view -> {
register_act.setText("");
register_pwd.setText("");
dialog.dismiss();
});
create.setOnClickListener(view -> {
accountPasswordData.setActPwdData(register_act.getText().toString(),register_pwd.getText().toString());
register_act.setText("");
register_pwd.setText("");
dialog.dismiss();
});
}
我設計先將Dialog給顯示出來,再來綁定了在Dialog上的物件id,然後就可以設計個別的點擊事件
cancel.setOnClickListener(view -> {
register_act.setText("");
register_pwd.setText("");
dialog.dismiss();
});
取消按鈕按下後,將兩個EditText清空,接著就把Dialog給關掉
create.setOnClickListener(view -> {
accountPasswordData.setActPwdData(register_act.getText().toString(),register_pwd.getText().toString());
register_act.setText("");
register_pwd.setText("");
dialog.dismiss();
});
建立按鈕按下後,呼叫AccountPasswordData的setActPwdData,並把要註冊的帳號跟密碼丟進去,到這裡就成功新增了一組帳密,接著一樣地將EditText清空,然後關閉Dialog。
private void checkActPwdData(String act, String pwd) {
ArrayList<HashMap<String,String>> data = accountPasswordData.getActPwdData();
for (int i = 0; i < data.size(); i++) {
if (data.get(i).get("Account").equals(act) && data.get(i).get("Password").equals(pwd)){
Intent intent = new Intent();
intent.setClass(this, MainActivity.class);
startActivity(intent);
}
else{
password.setText("");
Log.d("test", "登入失敗");
}
}
}
首先我建立了一個ArrayList去跟AccountPasswordData要取存放帳密資料的陣列,接著用for迴圈去一組一組的對取傳進來到帳號跟密碼,再來成功的話就會執行跳轉頁面的指令
Intent intent = new Intent();
intent.setClass(this, MainActivity.class);
startActivity(intent);
使用Intent
就可以執行跳轉的功能,首先建立一個Intent,接著用setClass
指定( 呼叫指令的頁面 , 目標頁面 )
,最後就是執行命令startActivity
,並將要執行的intent放進去,就可以順利跳轉頁面囉~
如果想要將一些資料給一起帶到下個Activity的話,可以使用putExtra、putExtras
這兩個指令,使用的方法都是先輸入Key
,然後輸入要傳入的Value
,兩個的差別在於前者可以放入各式個樣的資料,但傳入大量的資料就沒那麼方便,後者則是可以傳入Bundle,利用Bundle可以像裡面存入資料的方式(Key跟Value),將大量的資料一次帶到下個Activity接收,接收資料的方式:
Intent intent = getIntent();
if (intent != null){
String data = intent.getStringExtra("Key");
String[] dataList = intent.getStringArrayExtra("Key");
ArrayList<HashMap<String,String>> arrayList = (ArrayList<HashMap<String, String>>) intent.getSerializableExtra("Key");
}
第一行接收了傳入的資料,接著可以使用if判斷式判斷intent是否為null,再決定要不要做接收資料的動作
String data = intent.getStringExtra("Key");
,當傳入的資料為String可以使用getStringExtra
來接收。intent.getStringArrayExtra("Key");
,當傳入的資料為List型態時可以使用,使用Bundle傳入資料的話,接收的部分也是這樣寫。intent.getSerializableExtra("Key");
,這個指令會使用在傳入的資料較複雜時,比如可能我往你面傳入ArrayList<HashMap<String,String>>的型態的資料的話,就必須要像範例中的那樣打,同樣的如果我傳入的是從其他class寫的資料,我也必須要用個方法接收。